<?

function dump($input,$key="...")
{
	$dump=new dump;
	$dump->data($input,$key);
	$dump->print_styled();
} 

function save_dump($input,$filename="var_dump.html",$return=false)
{
	$dump=new dump;
	$dump->data($input,$key);
	$link=$dump->save($filename);
	if($return){
		echo $link;
	}
} 

function search_dump($input,$search)
{
	$dump=new dump;
	$input=$dump->search($input,$search);
	$dump->data($input,$key);
	$dump->print_styled();	
}

function trace_dump()
{
	$dump=new dump;
	$dump->data(debug_backtrace(),$key);
	$dump->print_styled();
}

if(!empty($_REQUEST["img"])){
	header("Content-type: image/gif");
	switch ($_REQUEST["img"]) {
		case "minus.gif":
			echo base64_decode(base64_encode(file_get_contents("Bilder/minus.gif")));
			break;
		
		case "plus.gif":
			echo base64_decode(base64_encode(file_get_contents("Bilder/plus.gif")));
			break;
			
		case "popup.gif":
			echo base64_decode(base64_encode(file_get_contents("Bilder/popup.gif")));
			break;
	}
}

/**
* Common Class to Dump data in an comprehensible fashion
*/
class dump
{
	var $template=array(
'ul'=>'
	<ul{class:ul}>
		{value:ul}
	</ul>',
'li'=>'
	<li{class:li}>
		<a onClick="popup(this)" title="open this part in a new window" class="icon">&nbsp;</div>
		<a onClick="dumpToggle(this)" title="{value:title}">
			{value:a}
		</a>
		{sub}
	</li>',
'text'=>'
	<li{class:li}>
		<div class="overflow">
			{value:li}
		</div>
	</li>',
'value'=>'
	<span title="{info}"><strong>{key}</strong>&nbsp;<em>({type})</em>&nbsp;<var>{value}</var></span>',
'table'=>'
	<div class="overflow">
		<table cellspacing="0px" cellpadding="0">
			{value:table}
		</table>
	</div>',
'table:head:item'=>
	'<th {config:th}>
		{value:th}
	</th>',
'table:item'=>
	'<td {config:td}>
		{value:td}
	</td>',
'table:row:even'=>
	'<tr class="even" {config:tr}>
		{value:tr}
	</tr>',
'table:row:odd'=>
	'<tr class="odd" {config:tr}>
		{value:tr}
	</tr>');

	public function StyleAndJS($overwrite=false)
	{
		if(!defined("dumpStyleAndJS")||$overwrite){
			$this->StyleAndJS="<script type='text/javascript' charset='utf-8' id='dumpJS'>".file_get_contents("dump.inc.js")."</script>";
			$this->StyleAndJS.="<style type='text/css' media='print' id='dumpStylePrint'>".file_get_contents("dump.inc.print.css")."</style>";
			$this->StyleAndJS.="<style type='text/css' media='screen' id='dumpStyle'>".file_get_contents("dump.inc.screen.css")."</style>";
			$this->return.=$this->StyleAndJS;
			define("dumpStyleAndJS",true);
		}
	}
	
	public function data($input,$key)
	{
		$this->StyleAndJS();
		$this->return.=$this->iterate($input,$key);
	}
	
	public function search($input,$search)
	{
		switch (TRUE) {
			case is_array($input):
				foreach ($input as $key => $value) {
					if(strpos($key,$search)!==FALSE){
						$return[$key]=$value;
					}else{
						$temp=$this->search($value,$search);
						if(!empty($temp)){
							$return[$key]=$temp;
						}
					}
				}
				return $return;
				break;
			
			case is_Object($input):
					
					break;	
			
			case is_Resource($input):
					
					break;	
				
			default:
				if(strpos($input,$search)!==FALSE){
					return $input;
				}
				break;
		}
	}
	
	public function recursionCheck(&$input)
	{
		switch (TRUE) {
			case is_array($input):
				foreach ($input as $key => $value) {
					if(is_array($value)){
						if(array_keys($input)==array_keys($value)){
							$input[$key]="Recursion";
						}
					}
				}
				break;
				
			default:
				break;
		}
	}
	
	public function iterate($inputValue,$inputKey)
	{	
		$this->recursionCheck($inputValue);
		
		if(empty($this->first)){
			$first=true;
			$this->first=1;
		}else{
			$first=false;
		}
		
		switch (!$first) {
			case FALSE:
				$first=false;
				$param=array(
					"class:ul"=>" class='dump ".gettype($inputValue)."'",
					"value:ul"=>$this->iterate($inputValue,$inputKey)
				);
				
				return $this->parse("ul",$param);
				break;
				
			case is_Array($inputValue):
				foreach ($inputValue as $key => $value) {
					$return.=$this->iterate($value,$key);
				}
				
				$param=array(
					"class:ul"=>" class='array'",
					"value:ul"=>$return
				);
				$return = $this->parse("ul",$param);
				
				
				$param["class:li"]=" class='hasSub'";
				$param["value:a"]=$this->getInfo($inputValue,$inputKey);
				$param["value:title"]=gettype($inputValue);
				$param["sub"]=$return;
				
				return $this->parse("li",$param);
				break;
			
			case is_Object($inputValue):
				$array=get_object_vars($inputValue);
				
				foreach ($array as $key => $value) {
					$return.=$this->iterate($value,$key);
				}
				
				$methods= get_class_methods($inputValue);
				
				foreach ($methods as $key => $value) {
					$return.=$this->iterate("method",$value);
				}
				
				$param=array(
					"class:ul"=>" class='object'",
					"value:ul"=>$return
				);
				$return = $this->parse("ul",$param);
				
				
				$param["class:li"]=" class='hasSub'";
				$param["value:a"]=$this->getInfo($inputValue,$inputKey);
				$param["value:title"]=gettype($inputValue);
				$param["sub"]=$return;
				
				return $this->parse("li",$param);
				break;
				
			case is_Resource($inputValue):
				switch (get_resource_type($inputValue)) {
					case 'mysql result':
						$param["value:a"]=$this->parseMysqlTable($inputValue);
						$param["value:title"]=gettype($inputValue);
						$return = $this->parse("li",$param);
						
						$param=array(
							"class:ul"=>" class='resource'",
							"value:ul"=>$return
						);
						$return = $this->parse("ul",$param);
						mysql_data_seek($inputValue,0);
						return $this->parseLi($this->getInfo($inputValue,$inputKey), $return,gettype($inputValue), " class='hasSub'");
						break;
					
					case 'mysql link':
						$param["value:a"]=$this->getInfo($inputValue,$inputKey);
						$param["value:title"]=gettype($inputValue);
						
						return $this->parse("li",$param);
						break;
					
					case 'stream':
						$metadata=stream_get_meta_data($inputValue);
						return $this->iterate($metadata,$inputKey);
						break;
						
					default:
						return get_resource_type($inputValue);
						break;
				}
				break;
				
			default:
				if(strlen($inputValue)>100){
					
					$return=$this->parseText($inputValue);
					
					$param=array(
						"class:ul"=>" class='text'",
						"value:ul"=>$return
					);
					$return = $this->parse("ul",$param);
					$param="";
					$param["class:li"]=" class='hasSub'";
				}
				
				$param["value:a"]=$this->getInfo($inputValue,$inputKey);
				$param["value:title"]=gettype($inputValue);
				$param["sub"]=$return;
				
				return $this->parse("li",$param);
				break;
		}
	}
	
	public function getInfo($input,$key){
		switch (TRUE) {
			case is_array($input):
				return $this->parseInfo($key,gettype($input).", ".count($input)." elements",$input);
				break;
				
			case is_object($input):
				return $this->parseInfo($key,gettype($input).", ".count(get_object_vars($input))." vars, ".count(get_class_methods($input))." methods",get_class($input));
				break;
			
			case ($input==="method"):
				return $this->parseInfo($key."()","method");
				break;
				
			case is_string($input):
				return $this->parseInfo($key,gettype($input).", ".strlen($input)." chars",htmlspecialchars(substr($input,0,100)));
				break;
				
			case is_resource($input):
				switch (get_resource_type($input)) {
					case "mysql result":
						return $this->parseInfo($key,get_resource_type($input).", ".mysql_num_rows($input)." rows",$input);
						break;
						
					case "mysql link":
						return $this->parseInfo($key,get_resource_type($input).", ".mysql_info($input),$input);
						break;
					
					default:
						return $this->parseInfo($key,gettype($input).", ".strlen($input)." chars",$input);
						break;
				}
				break;
				
			default:
				return $this->parseInfo($key,gettype($input),$input);
				break;
		}
	}
	
	public function parseInfo($key,$type,$value="",$info=""){
		$param["type"]=$type;
		$param["key"]=$key;
		$param["info"]=$info;
		$param["value"]=$value;
		return $this->parse("value",$param);
	}
	
	public function parseLi($a,$sub,$title="",$class=""){
		$param["class:li"]=$class;
		$param["value:a"]=$a;
		$param["value:title"]=$title;
		$param["sub"]=$sub;
		return $this->parse("li",$param);
	}
	
	public function parseText($value,$class=""){
		$param["class:li"]=$class;
		$param["value:li"]="<pre>".htmlspecialchars($value)."</pre>";
		return $this->parse("text",$param);
	}
	
	public function parse($element,$param)
	{
		$element=$this->template[$element];
		foreach ($param as $key => $value) {
			$key=$key ? $key : gettype($key);
			$element=str_replace("{".$key."}",$value,$element);
		}
		$element=$this->cleanup($element);
		return $element;
	}
	
	public function parseMysqlTable($result)
	{
		while($array=mysql_fetch_assoc($result)){
			$data[]=$array;
		}
		return $this->parseTable($data,$header);
	}
	
	public function parseTable($input,$header=false)
	{
		$head=true;
		$count=0;
		foreach($input as $array){
			$row="";
			$param="";
			$param["value:th"]=$count++;
			$row.=$this->parse("table:head:item",$param);
			
			if($head){
				$head=false;
				$param="";
				$param["value:th"]="";
				$headRow.=$this->parse("table:head:item",$param);
				foreach ($array as $key => $value) {
					$param="";
					$param["value:th"]=$key;
					$headRow.=$this->parse("table:head:item",$param);
				}
				$param="";
				$param["value:tr"]=$headRow;
				$return.=$this->parse("table:row:even",$param);
			}
			
			foreach ($array as $key => $value) {
				$param="";
				$param["value:td"]=$value;
				$row.=$this->parse("table:item",$param);
			}
			$param="";
			$param["value:tr"]=$row;
			
			if($switch){
				$switch=false;
				$return.=$this->parse("table:row:odd",$param);
			}else{
				$switch=true;
				$return.=$this->parse("table:row:even",$param);
			}
		}
		$param=array(
			"value:table"=>$return
		);
		$return = $this->parse("table",$param);
		return $return;
	}
	
	public function cleanup($input)
	{
		return preg_replace("/\{[^}]+}/","",$input);
	}
	
	public function print_styled()
	{
		echo $this->return;
	}
	
	public function getPath()
	{
		$includes=get_included_files();
		foreach ($includes as $key => $value) {
			if(stristr($value,"dump.inc.php")){
				$path=str_replace("dump.inc.php","",str_replace("\\","/",$value));
			}
		}
		$root=$this->getRoot();
		$path = str_replace($root,"",$path);
		return $path;
	}
	
	public function getLink()
	{
	    $path=$this->getPath();
	    $domain=$_SERVER["SERVER_NAME"];
	    return "http://".$domain.$path;
	}
	
	public function getRoot()
	{
		$root=$_SERVER["DOCUMENT_ROOT"];
		return $root;
	}
	
	public function save($filename)
	{
			$filename=$filename;
			if(!defined("dump".$filename)){
				$this->StyleAndJS(true);
				define("dump".$filename,true);
			}
			
			if(defined("dumpSave".$filename))
		    {
		    	file_put_contents($this->getRoot().$this->getPath().$filename,$this->return,FILE_APPEND);
		    }else{
		    	file_put_contents($this->getRoot().$this->getPath().$filename,$this->return);
		    	define("dumpSave".$filename,true);
		    }
		    return '<a href="'.$this->getLink().$filename.'">'.$filename.'</a>';
		
	}
}
?>